package com.fin.zw.intelligentbot.service;

import com.fin.zw.intelligentbot.entity.*;
import com.fin.zw.intelligentbot.enums.SourceType;
import com.fin.zw.intelligentbot.model.request.SceneInfoRequest;
import com.fin.zw.intelligentbot.model.response.SceneInfoResponse;
import com.fin.zw.intelligentbot.model.session.SessionModel;
import com.fin.zw.intelligentbot.repository.*;
import com.google.common.collect.Sets;
import com.querydsl.core.BooleanBuilder;
import org.apache.commons.collections4.IterableUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.Set;

@Service("sceneInfoService")
public class SceneInfoService {
    private static Logger logger = LoggerFactory.getLogger(SceneInfoService.class);

    @Autowired
    private SceneInfoRepository sceneInfoRepository;

    @Autowired
    private RobotInfoRepository robotInfoRepository;

    @Autowired
    private DialTaskRepository dialTaskRepository;

    @Autowired
    private CommonService commonService;

    @Autowired
    private VariableRepository variableRepository;

    @Autowired
    private CategoryLabelRepository categoryRepository;


    /**
     * 分页查询场景信息
     * @param pageable
     * @param request
     * @param sessionModel
     * @return
     */
    public Page<SceneInfoResponse> querySceneInfoAll(Pageable pageable,
                                                     SceneInfoRequest request,
                                                     SessionModel sessionModel){
        BooleanBuilder builder = new BooleanBuilder();
        QSceneInfo qSceneInfo = QSceneInfo.sceneInfo;
        if(sessionModel.getCompanyId() != null){
            builder.and(qSceneInfo.companies.contains(commonService.getCompany(sessionModel)));
        }else{ //超级管理方
            builder.and(qSceneInfo.source.eq(SourceType.SAFEMANAGER));
        }
        if(request.getName() != null){ //场景名称
            builder.and(qSceneInfo.name.like("%".concat(request.getName()).concat("%")));
        }
        if(request.getCode() != null){ //场景编号
            builder.and(qSceneInfo.code.eq(request.getCode()));
        }
        Page<SceneInfo> sceneInfoPage = sceneInfoRepository.findAll(builder,pageable);
        Page<SceneInfoResponse> page = sceneInfoPage.map(sceneInfo -> {
            SceneInfoResponse response = new SceneInfoResponse();
            BeanUtils.copyProperties(sceneInfo,response);
            return response;
        });
        return page;
    }

    /**
     * 查询对应的场景信息
     * @param sessionModel
     * @return
     */
    public List<SceneInfo> getSceneInfoList(SessionModel sessionModel){
        BooleanBuilder builder = new BooleanBuilder();
        QSceneInfo qSceneInfo = QSceneInfo.sceneInfo;
        if(sessionModel.getCompanyId() != null){
            builder.and(qSceneInfo.companies.contains(commonService.getCompany(sessionModel)));
        }else{ //超级管理方
            builder.and(qSceneInfo.source.eq(SourceType.SAFEMANAGER));
        }
        Iterable<SceneInfo> iterable = sceneInfoRepository.findAll(builder);
        List<SceneInfo> list = IterableUtils.toList(iterable);
        return list;
    }

    /**
     * 场景信息的创建
     * @param request
     * @param sessionModel
     */
    public void createSceneInfo(SceneInfoRequest request,
                                SessionModel sessionModel){
        SceneInfo sceneInfo = new SceneInfo();
        BeanUtils.copyProperties(request,sceneInfo);
        Set<Company> companySet = commonService.getCompanySet(sessionModel,request.getCompanyIds());
        sceneInfo.setCompanies(companySet);

        this.setVariableAndCategory(request, sceneInfo);

        if (StringUtils.isEmpty(sessionModel.getCompanyId())) { //管理端
            sceneInfo.setSource(SourceType.SAFEMANAGER);
        }else{ //企业方
            sceneInfo.setSource(SourceType.COMPANY);
        }

        sceneInfoRepository.save(sceneInfo);
    }

    private void setVariableAndCategory(SceneInfoRequest request, SceneInfo sceneInfo) {
        Iterator<Variable> vars =variableRepository
                .findAll(QVariable.variable.id.in(request.getVariableIds()))
                .iterator();

        sceneInfo.setVariables(Sets.newHashSet(vars));

        Iterator<CategoryLabel> cates =categoryRepository
                .findAll(QCategoryLabel.categoryLabel.id.in(request.getCategoryIds()))
                .iterator();
        sceneInfo.setCategories(Sets.newHashSet(cates));
    }

    /**
     * 场景信息的更新
     * @param request
     * @param sessionModel
     */
    public void updateSceneInfo(SceneInfoRequest request,
                                SessionModel sessionModel){
        SceneInfo sceneInfo = checkExist(request.getId(), sessionModel);
        //拷贝简单属性
        BeanUtils.copyProperties(request,sceneInfo,"companyIds","categoryIds","variableIds");

        //重新设置企业信息
        Set<Company> companySet = commonService.getCompanySet(sessionModel,request.getCompanyIds());
        sceneInfo.setCompanies(companySet);

        //重新设置变量与分类
        this.setVariableAndCategory(request,sceneInfo);
        sceneInfoRepository.save(sceneInfo);
    }


    /**
     * 场景的删除
     * @param id
     * @param sessionModel
     */
    public void deleteSceneInfo(String id,SessionModel sessionModel){
        SceneInfo sceneInfo = checkExist(id, sessionModel);
        //需要检测机器人是否有绑定，如果有绑定则不允许删除，如果没有则正常删除
        Iterator<RobotInfo> infoIterator = robotInfoRepository.findAll(QRobotInfo.robotInfo.sceneInfo.id.eq(id)).iterator();
        if(infoIterator.hasNext()){
            logger.info("该场景已经绑定机器人，请先解除绑定");
            throw new RuntimeException("该场景已经绑定机器人，请先解除绑定");
        }
        //监测在任务中是否绑定
        Iterator<DialTask> dialTaskIterator = dialTaskRepository.findAll(QDialTask.dialTask.scene.id.eq(id)).iterator();
        if(dialTaskIterator.hasNext()){
            logger.info("该场景已经绑定任务，请先解除绑定");
            throw new RuntimeException("该场景已经绑定任务，请先解除绑定");
        }
        sceneInfoRepository.delete(sceneInfo);
    }

    private SceneInfo checkExist(String id, SessionModel sessionModel) {
        Optional<SceneInfo> optional = sceneInfoRepository.findById(id);
        if(!optional.isPresent()){
            logger.info("更新的场景信息不存在");
            throw new RuntimeException("更新的场景信息不存在");
        }
        SceneInfo sceneInfo = optional.get();
        String error = commonService.exitSource(sessionModel,sceneInfo.getSource());
        if(error != null){
            logger.info(error);
            throw new RuntimeException(error);
        }
        return sceneInfo;
    }
}
